#include <stdio.h>
#include <string.h>
#include "page.h"
#include <string.h>
// 页头访问宏
#define HDR(p) ((PageHeader*)(p->data))
// 槽数组指针访问宏（槽从页尾向上增长）
#define SLOTS_PTR(p) ((Slot*)((uint8_t*)p->data + PAGE_SIZE - sizeof(Slot) * HDR(p)->slot_count))

// 初始化页面结构
// 参数：
// - p: 要初始化的页面指针
void page_init(Page *p){
    memset(p->data, 0, PAGE_SIZE);
    HDR(p)->free_start = sizeof(PageHeader);
    HDR(p)->slot_count = 0;
    HDR(p)->free_bytes = PAGE_SIZE - sizeof(PageHeader);
}

// 确保页面有足够的槽位
// 参数：
// - p: 页面指针
// 返回值：成功返回新槽ID，失败返回-1
static int ensure_slot(Page *p){
    // 需要扩一条槽：从页尾向上分配
    uint16_t need = sizeof(Slot);
    if (HDR(p)->free_bytes < need) {
        return -1;
    }
    HDR(p)->free_bytes -= need;
    HDR(p)->slot_count += 1;
    int new_slot_id = HDR(p)->slot_count - 1;
    return new_slot_id;
}

// 向页面插入记录
int page_insert(Page *p, const void *rec, uint16_t len, int *slot_id_out){
    // 参数验证
    if (!p || !rec || len == 0 || len > PAGE_SIZE) {
        return -1; // 无效参数
    }
    
    // 需要空间：len + 一个槽
    uint16_t need = len + sizeof(Slot);
    if (HDR(p)->free_bytes < need) {
        return -1; // 空间不足
    }

    int slot_id = ensure_slot(p);
    if (slot_id < 0) {
        return -1; // 无法创建槽
    }

    // 记录从 free_start 位置写入
    // 增强边界检查
    if (HDR(p)->free_start + len > PAGE_SIZE || HDR(p)->free_start < sizeof(PageHeader)) {
        return -2; // 写入会超出页面边界或位置无效
    }
    
    // 确保不会覆盖槽区域
    uint16_t slots_area_start = PAGE_SIZE - sizeof(Slot) * HDR(p)->slot_count;
    if (HDR(p)->free_start + len > slots_area_start) {
        return -3; // 数据会覆盖槽区域
    }
    
    memcpy(p->data + HDR(p)->free_start, rec, len);
    
    // 验证写入的数据
    if (memcmp(p->data + HDR(p)->free_start, rec, len) != 0) {
        fprintf(stderr, "Warning: Data verification failed during page_insert\n");
    }
    
    // 使用SLOTS_PTR宏计算槽位置
    Slot *slots = SLOTS_PTR(p);
    
    // 确保槽索引有效
    if (slot_id >= HDR(p)->slot_count) {
        return -3; // 槽索引无效
    }
    
    slots[slot_id].off = HDR(p)->free_start;
    slots[slot_id].len = len;

    HDR(p)->free_start += len;
    HDR(p)->free_bytes -= len;            
    
    if (slot_id_out) *slot_id_out = slot_id;
    return 0;
}

// 从页面获取记录
int page_get(const Page *p, int slot_id, const void **rec, uint16_t *len){
    
    if (slot_id < 0 || slot_id >= HDR(p)->slot_count) {
        return -1;
    }
    
    // 使用SLOTS_PTR宏计算槽位置
    const Slot *slots = SLOTS_PTR(p);
    
    if (slots[slot_id].len == 0) {
        return -2; // deleted
    }
    
    // 检查偏移量是否有效
    if (slots[slot_id].off >= PAGE_SIZE || slots[slot_id].off + slots[slot_id].len > PAGE_SIZE) {
        return -3; // invalid offset
    }
    
    *rec = p->data + slots[slot_id].off;
    *len = slots[slot_id].len;
    
    return 0;
}

int page_delete(Page *p, int slot_id){
    if (slot_id < 0 || slot_id >= HDR(p)->slot_count) return -1;
    Slot *slots = SLOTS_PTR(p);
    slots[slot_id].len = 0; // 逻辑删除
    return 0;
}

int page_compact(Page *p){ (void)p; return 0; } 
